package com.yix.common.utils;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

/**
 * @author wdx
 * @version 1.0
 * @Description TODO
 * @date 2021/1/26 14:02
 */
public class JacobHelper {
    // word文档
    private Dispatch doc;
    // word运行程序对象
    private ActiveXComponent word;
    // 所有word文档集合
    private Dispatch documents;
    // 选定的范围或插入点
    private Dispatch selection;

    public JacobHelper(boolean visible) throws Exception {
        ComThread.InitSTA();//线程启动
        if (word == null) {
            word = new ActiveXComponent("Word.Application");
            word.setProperty("Visible", new Variant(visible)); // 不可见打开word
            word.setProperty("AutomationSecurity", new Variant(3)); // 禁用宏
        }
        if (documents == null) {
            documents = word.getProperty("Documents").toDispatch();
        }
    }
    /**
     * 关闭文档
     *
     * @param val
     * 0不保存修改 -1 保存修改 -2 提示是否保存修改
     */
    public void closeDocument(int val) {
        if(doc != null){
            Dispatch.call(doc, "Close", new Variant(val));//注 是documents而不是doc
        }
        documents = null;
        doc = null;
    }
    /**
     * 保存并关闭全部应用
     *
     */
    public void close() {
        closeDocument(-1);
        if (word != null) {
            //Dispatch.call(word, "Quit");
            word.invoke("Quit", new Variant[] {});
            word = null;
        }
        selection = null;
        documents = null;
        ComThread.Release();//释放com线程。根据jacob的帮助文档，com的线程回收不由java的垃圾回收器处理
    }
    /**
     * 创建一个新的word文档
     *
     */
    public void createNewDocument() {
        doc = Dispatch.call(documents, "Add").toDispatch();
        selection = Dispatch.get(word, "Selection").toDispatch();
    }
    /**
     * 打开一个已存在的文档
     *
     * @param docPath
     */
    public void openDocument(String docPath) {
        doc = Dispatch.call(documents, "Open", docPath).toDispatch();
        selection = Dispatch.get(word, "Selection").toDispatch();
    }
    /**
     * 只读方式打开一个加密的文档
     *
     * @param docPath-文件全名
     * @param pwd-密码
     */
    public void openDocumentOnlyRead(String docPath, String pwd)
            throws Exception {
        //closeDocument();
        doc = Dispatch.callN(
                documents,
                "Open",
                new Object[] { docPath, new Variant(false), new Variant(true),
                        new Variant(true), pwd, "", new Variant(false) })
                .toDispatch();
        selection = Dispatch.get(word, "Selection").toDispatch();
    }
    /**
     * 打开一个加密的文档
     * @param docPath
     * @param pwd
     * @throws Exception
     */
    public void openDocument(String docPath, String pwd) throws Exception {
        //closeDocument();
        doc = Dispatch.callN(
                documents,
                "Open",
                new Object[] { docPath, new Variant(false), new Variant(false),
                        new Variant(true), pwd }).toDispatch();
        selection = Dispatch.get(word, "Selection").toDispatch();
    }
    /**
     * 保存文档
     * @param savePath
     */
    public void save(String savePath){
        Dispatch.call(Dispatch.call(word, "WordBasic").getDispatch(),"FileSaveAs", savePath);
    }
    /**
     * 文档另存为
     * @param savePath 全部地址eg：D://doc//test.doc
     */
    public void saveAs(String savePath){
        Dispatch.call(doc, "SaveAs", new Variant(savePath));
    }
    /**
     * 在当前插入点插入字符串
     *
     * @param newText
     *            要插入的新字符串
     */
    public void insertText(String newText) {
        Dispatch.put(selection, "Text", newText);
    }
    /**
     * 从选定内容或插入点开始查找文本
     *
     * @param toFindText
     *            要查找的文本
     * @return boolean true-查找到并选中该文本，false-未查找到文本
     */
    @SuppressWarnings("static-access")
    public boolean find(String toFindText) {
        if (toFindText == null || toFindText.equals("")) {
            return false;
        }
        // 从selection所在位置开始查询
        Dispatch find = word.call(selection, "Find").toDispatch();
        // 设置要查找的内容
        Dispatch.put(find, "Text", toFindText);
        // 向前查找
        Dispatch.put(find, "Forward", "True");
        // 设置格式
        Dispatch.put(find, "Format", "True");
        // 大小写匹配
        Dispatch.put(find, "MatchCase", "True");
        // 全字匹配
        Dispatch.put(find, "MatchWholeWord", "false");
        // 查找并选中
        return Dispatch.call(find, "Execute").getBoolean();
    }
    /**
     * 把选定选定内容设定为替换文本
     *
     * @param toFindText
     *            查找字符串
     * @param newText
     *            要替换的内容
     * @return
     */
    public boolean replaceText(String toFindText, String newText) {
        if (!find(toFindText)) {
            return false;
        }
        Dispatch.put(selection, "Text", newText);
        return true;
    }
    /**
     * 全局替换文本
     *
     * @param toFindText
     *            查找字符串
     * @param newText
     *            要替换的内容
     */
    public void replaceAllText(String toFindText, String newText) {
        while (find(toFindText)) {
            Dispatch.put(selection, "Text", newText);
            Dispatch.call(selection, "MoveRight");
        }
    }
    /**
     * 设置当前选定内容的字体
     *
     *            下划线
     * @param colorSize
     *            字体颜色
     * @param size
     *            字体大小
     * @param name
     *            字体名称
     * @param hidden
     *            是否隐藏
     */
    public void setFont(boolean bold, boolean italic, boolean underLine,
                        String colorSize, String size, String name,boolean hidden) {
        Dispatch font = Dispatch.get(selection, "Font").toDispatch();
        Dispatch.put(font, "Name", new Variant(name));
        Dispatch.put(font, "Bold", new Variant(bold));
        Dispatch.put(font, "Italic", new Variant(italic));
        Dispatch.put(font, "Underline", new Variant(underLine));
        Dispatch.put(font, "Color", colorSize);
        Dispatch.put(font, "Size", size);
        Dispatch.put(font, "Hidden", hidden);
    }
    /**
     * 文件保存为html格式
     *
     * @param htmlPath
     */
    public void saveAsHtml(String htmlPath) {
        Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {
                htmlPath, new Variant(8) }, new int[1]);
    }
    /**
     * 把选定的内容或插入点向上移动
     *
     * @param pos
     */
    public void moveUp(int pos) {
        move("MoveUp", pos);
    }

    /**
     * 把选定的内容或者插入点向下移动
     *
     * @param pos
     */
    public void moveDown(int pos) {
        move("MoveDown", pos);
    }

    /**
     * 把选定的内容或者插入点向左移动
     *
     * @param pos
     */
    public void moveLeft(int pos) {
        move("MoveLeft", pos);
    }

    /**
     * 把选定的内容或者插入点向右移动
     *
     * @param pos
     */
    public void moveRight(int pos) {
        move("MoveRight", pos);
    }

    /**
     * 把选定的内容或者插入点向右移动
     */
    public void moveRight() {
        Dispatch.call(getSelection(), "MoveRight");
    }

    /**
     * 把选定的内容或者插入点向指定的方向移动
     * @param actionName
     * @param pos
     */
    private void move(String actionName, int pos) {
        for (int i = 0; i < pos; i++) {
            Dispatch.call(getSelection(), actionName);
        }
    }

    /**
     * 把插入点移动到文件首位置
     */
    public void moveStart(){
        Dispatch.call(getSelection(), "HomeKey", new Variant(6));
    }

    /**
     * 把插入点移动到文件末尾位置
     */
    public void moveEnd(){
        Dispatch.call(getSelection(), "EndKey", new Variant(6));
    }
    /**
     * 获取当前的选定的内容或者插入点
     * @return 当前的选定的内容或者插入点
     */
    public Dispatch getSelection(){
        if (selection == null) {
            selection = Dispatch.get(word, "Selection").toDispatch();
        }
        return selection;
    }
    /**
     * 进入页眉视图
     */
    public void headerView(){
        //取得活动窗体对象
        Dispatch ActiveWindow = word.getProperty( "ActiveWindow").toDispatch();
        //取得活动窗格对象
        Dispatch ActivePane = Dispatch.get(ActiveWindow, "ActivePane").toDispatch();
        //取得视窗对象
        Dispatch view = Dispatch.get(ActivePane, "View").toDispatch();
        Dispatch.put(view, "SeekView", "9");
    }

    /**
     * 进入页脚视图
     */
    public void footerView(){
        //取得活动窗体对象
        Dispatch ActiveWindow = word.getProperty( "ActiveWindow").toDispatch();
        //取得活动窗格对象
        Dispatch ActivePane = Dispatch.get(ActiveWindow, "ActivePane").toDispatch();
        //取得视窗对象
        Dispatch view = Dispatch.get(ActivePane, "View").toDispatch();
        Dispatch.put(view, "SeekView", "10");
    }

    /**
     * 进入普通视图
     */
    public void pageView(){
        //取得活动窗体对象
        Dispatch ActiveWindow = word.getProperty( "ActiveWindow").toDispatch();
        //取得活动窗格对象
        Dispatch ActivePane = Dispatch.get(ActiveWindow, "ActivePane").toDispatch();
        //取得视窗对象
        Dispatch view = Dispatch.get(ActivePane, "View").toDispatch();
        Dispatch.put(view, "SeekView", new Variant(0));//普通视图
    }
    /**
     * 将指定的文本替换成图片
     * @param findText
     * @param imagePath
     * @return boolean true-查找到并替换该文本，false-未查找到文本
     */
    public boolean replaceImage(String findText, String imagePath, int width, int height){
        moveStart();
        if (!find(findText)) {
            return false;
        }
        Dispatch picture = Dispatch.call(Dispatch.get(getSelection(), "InLineShapes").toDispatch(), "AddPicture", imagePath).toDispatch();
        Dispatch.call(picture, "Select");
        Dispatch.put(picture, "Width", new Variant(width));
        Dispatch.put(picture, "Height", new Variant(height));
        moveRight();
        return true;
    }

    /**
     * 全局将指定的文本替换成图片
     * @param findText
     * @param imagePath
     */
    public void replaceAllImage(String findText, String imagePath, int width, int height){
        moveStart();
        while (find(findText)){
            Dispatch picture = Dispatch.call(Dispatch.get(getSelection(), "InLineShapes").toDispatch(), "AddPicture", imagePath).toDispatch();
            Dispatch.call(picture, "Select");
            Dispatch.put(picture, "Width", new Variant(width));
            Dispatch.put(picture, "Height", new Variant(height));
            moveStart();
        }
    }

    /**
     * 在当前插入点中插入图片
     * @param imagePath
     */
    public void insertImage(String imagePath, int width, int height){
        Dispatch picture = Dispatch.call(Dispatch.get(getSelection(), "InLineShapes").toDispatch(), "AddPicture", imagePath).toDispatch();
        Dispatch.call(picture, "Select");
        Dispatch.put(picture, "Width", new Variant(width));
        Dispatch.put(picture, "Height", new Variant(height));
        moveRight();
    }

    /**
     * 在当前插入点中插入图片
     * @param imagePath
     */
    public void insertImage(String imagePath){
        Dispatch.call(Dispatch.get(getSelection(), "InLineShapes").toDispatch(), "AddPicture", imagePath);
    }

    /**
     * 获取书签的位置
     * @param bookmarkName
     * @return 书签的位置
     */
    public Dispatch getBookmark(String bookmarkName){
        try{
            Dispatch bookmark = Dispatch.call(this.doc, "Bookmarks", bookmarkName).toDispatch();
            return Dispatch.get(bookmark, "Range").toDispatch();
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    @SuppressWarnings("static-access")
    public boolean deleteBookMark(String bookmarkName){
        Dispatch bookmark = Dispatch.call(this.doc, "Bookmarks", bookmarkName).toDispatch();
        if(bookmark !=null){
            Dispatch.call(bookmark, "Delete");
            return true;
        }else {
            return false;
        }
    }
    /**
     * 在指定的书签位置插入图片
     * @param bookmarkName
     * @param imagePath
     */
    public void insertImageAtBookmark(String bookmarkName, String imagePath){
        Dispatch dispatch = getBookmark(bookmarkName);
        if(dispatch != null) {
            Dispatch.call(Dispatch.get(dispatch, "InLineShapes").toDispatch(), "AddPicture", imagePath);
        }
    }

    /**
     * 在指定的书签位置插入图片
     * @param bookmarkName
     * @param imagePath
     * @param width
     * @param height
     */
    public void insertImageAtBookmark(String bookmarkName, String imagePath, int width, int height){
        Dispatch dispatch = getBookmark(bookmarkName);
        if(dispatch != null){
            Dispatch picture = Dispatch.call(Dispatch.get(dispatch, "InLineShapes").toDispatch(), "AddPicture", imagePath).toDispatch();
            Dispatch.call(picture, "Select");
            Dispatch.put(picture, "Width", new Variant(width));
            Dispatch.put(picture, "Height", new Variant(height));
        }
    }

    /**
     * 在指定的书签位置插入文本
     * @param bookmarkName
     * @param text
     */
    public void insertAtBookmark(String bookmarkName, String text){
        Dispatch dispatch = getBookmark(bookmarkName);
        if(dispatch != null) {
            Dispatch.put(dispatch, "Text", text);
        }
    }
}
